DeriveGamemode( "Gear" );
DeriveGamemode( "sandbox" );

--include( "BananaVGUI/panel.lua" );
--include( "BananaVGUI/scrolling.lua" );

include( "shared.lua" );
include( "cl_hud.lua" );
include( "cl_chat.lua" );
include( "player_shared.lua" );
include( "cl_playermenu.lua" );
include( "cl_weather.lua" );
include( "cl_charactermenu.lua" );
include( "cl_scoreboard.lua" );
include( "cl_accountcreation.lua" );
include( "cl_business.lua" );
include( "cl_inventory.lua" );
include( "cl_dev.lua" );
include( "cl_radiochat.lua" );
include( "cl_weaponselect.lua" );
include( "entity_shared.lua" );
include( "cl_admin.lua" );
include( "cl_storage.lua" );
include( "cl_help.lua" );
include( "cl_update.lua" );
include( "cl_umsg.lua" );
include( "cl_openingscreen.lua" );
include( "factions.lua" );

TS.StartTime = CurTime();
TS.FancyGayIntro = true;
TS.MapView = true;
TS.HighestHealth = 0;
TS.Christmas = true

TS.InCharacterCreate = false;

gui.EnableScreenClicker( false );

---------------------------------------
-- CLIENT HOOKS
---------------------------------------

function GM:Think()

	if( LocalPlayer():Health() > TS.HighestHealth ) then
	
		TS.HighestHealth = LocalPlayer():Health();
	
	end
	
	if( not LocalPlayer():Alive() ) then
	
		CinematicBarDesiredHeight = 0;
	
	end

	if( not ClientVars["FreezeHead"] ) then
		FreezeHeadViewAngle = nil;
		FreezeHeadStartAngle = nil;	           
	end
	           
	if( PlayerMenuVisible ) then
		PlayerMenuThink();
	end
	                          
	FillWeaponTabs();

	local weap = LocalPlayer():GetActiveWeapon();
	
	if( weap:IsValid() and weap:GetTable() and weap:GetTable().Primary ) then
	
		if( not ClientVars["Holstered"] and weap:GetTable().Primary.IronSightPos ) then
	
			if( weap:GetTable().Primary.ChargePos and weap:GetTable().CanCharge ) then
			
				local check = false;
				
				if( LocalPlayer():KeyDown( IN_ATTACK ) ) then
					if( weap:GetTable().PrimaryCharge ) then
						check = true;
					end
				end
				
				if( LocalPlayer():KeyDown( IN_ATTACK2 ) ) then
					if( weap:GetTable().SecondaryCharge ) then
						check = true;
					end
				end
		
				if( check and weap:GetTable():CanCharge() ) then
			
					weap:GetTable().Primary.PositionMode = 4;
					weap:GetTable().Primary.PositionMul = math.Clamp( weap:GetTable().Primary.PositionMul + ( 1 / weap:GetTable().Primary.PositionTime ) * FrameTime(), 0, 1 );

				elseif( weap:GetTable().Primary.PositionMode == 4 ) then
				
					if( weap:GetTable().RealPrimaryAttack ) then
						weap:GetTable():RealPrimaryAttack( LocalPlayer() );
					end
		
					weap:GetTable().Primary.PositionMul = 0;		
				
					if( weap:GetTable().Primary.PositionMul == 0 ) then
						weap:GetTable().Primary.PositionMode = 0;
					end
	
				end

			end
			
			if( not weap:GetTable().SecondaryCharge ) then
		
				if( LocalPlayer():KeyDown( IN_ATTACK2 ) and not weap:GetNetworkedBool( "reloading", false ) ) then
				
					weap:GetTable().Primary.PositionMode = 1;
					weap:GetTable().Primary.PositionMul = math.Clamp( weap:GetTable().Primary.PositionMul + ( 1 / weap:GetTable().Primary.PositionTime ) * FrameTime(), 0, 1 );
					--[[
					if( not weap:GetTable().Primary.PositionOffsetSet ) then
						weap:GetTable().Primary.PositionPosOffset = Vector( math.Rand( -.4, .4 ), math.Rand( -.4, .4 ), math.Rand( -.4, .4 ) );	
						weap:GetTable().Primary.PositionAngleOffset = Vector( math.Rand( -.4, .4 ), math.Rand( -.4, .4 ), math.Rand( -.4, .4 ) );
						weap:GetTable().Primary.PositionOffsetSet = true;
					end
					]]--
				elseif( weap:GetTable().Primary.PositionMode == 1 ) then
				
					if( SeeSniperScope ) then
					
						RunConsoleCommand( "eng_seescope", "0" );
						SeeSniperScope = false;
		
					end
				
					weap:GetTable().Primary.PositionMul = math.Clamp( weap:GetTable().Primary.PositionMul - ( 1 / weap:GetTable().Primary.PositionTime ) * FrameTime(), 0, 1 );		
				
					weap:GetTable().Primary.PositionOffsetSet = false;
				
					if( weap:GetTable().Primary.PositionMul == 0 ) then
						weap:GetTable().Primary.PositionMode = 0;
					end
				
				end
				
			end
		
		end
		
		--While we're unholstering it
		if( weap:GetTable().Primary.PositionMode == 2 ) then
		
			if( weap:GetTable().Primary.HolsteredPos ) then
	
				weap:GetTable().Primary.PositionMul = math.Clamp( weap:GetTable().Primary.PositionMul - ( 1 / weap:GetTable().Primary.PositionTime ) * FrameTime(), 0, 1 );		
			
				if( weap:GetTable().Primary.PositionMul == 0 ) then
					weap:GetTable().Primary.PositionMode = 0;
				end
					
	
			end
			
		end
		
		--While we're holstering it
		if( weap:GetTable().Primary.PositionMode == 3 ) then
		
			if( weap:GetTable().Primary.HolsteredPos ) then
		
				weap:GetTable().Primary.PositionMul = math.Clamp( weap:GetTable().Primary.PositionMul + ( 1 / weap:GetTable().Primary.PositionTime ) * FrameTime(), 0, 1 );		
			
				if( weap:GetTable().Primary.PositionMul == 1 ) then
					--RunConsoleCommand( "eng_hideviewmodel", "" );
				end
	
			end
			
		end
		
	end
	
end

UnconsciousFov = 90;
UnconsciousFovPing = false;
UnconsciousFovVel = -30;

DeathAngle = 0;

local function AddAlcoholMod( view )

	local mul = ClientVars["DrunkMul"];
	
	--We dont start caring until the multiplier hits a third of the way
	if( mul > .3 ) then
	
		mul = mul - .3;

		AlcoholBlur.HeadBobCosine = AlcoholBlur.HeadBobCosine + 120 * FrameTime();
		
		if( AlcoholBlur.HeadBobCosine > 360 ) then
		
			AlcoholBlur.HeadBobCosine = AlcoholBlur.HeadBobCosine - 360;
			AlcoholBlur.ShiftedPitchYaw = false;

		end
		
		if( AlcoholBlur.HeadBobCosine > 90 and not AlcoholBlur.ShiftedPitchYaw ) then
		
			--AlcoholBlur.HeadBobPitchMul = ( { -1, 1 } )[math.random( 1, 2 )];
			AlcoholBlur.HeadBobYawMul = math.Rand( -1, 1 );
			AlcoholBlur.ShiftedPitchYaw = true;
			AlcoholBlur.HeadBobCosine = 90;

		end
		
		local bobdist = math.cos( 3.14159265 * ( AlcoholBlur.HeadBobCosine / 180 ) );
		
		view.angles.pitch = view.angles.pitch + ( bobdist * ( 8 * mul * AlcoholBlur.HeadBobPitchMul ) );
		view.angles.yaw = view.angles.yaw + ( bobdist * ( 6 * mul * AlcoholBlur.HeadBobYawMul ) );

	end

	return view;

end

local HeadBob = {

	Dir = 1,
	Pitch = 0,
	Roll = 0,
	RollDesp = 0,
	NewRoll = true,

}

function GM:CalcView( ply, origin, angles, fov )

	--Msg( "Vector( " .. origin.x .. ", " .. origin.y .. ", " .. origin.z .. " )\n" );
	--Msg( "Angle( " .. angles.p .. ", " .. angles.y .. ", " .. angles.r .. " )\n" );

	local view = CalcView( ply, origin, angles, fov );
	
	if( not view ) then
	
		view = { }
	
		view.origin = origin;
		view.angles = angles;
		view.fov = fov;
	
	end
	
	if( not LocalPlayer():Alive() and ply:GetRagdollEntity() and ply:GetRagdollEntity():IsValid() ) then
	
		local trace = { }
		trace.start = ply:GetRagdollEntity():GetAttachment( ply:GetRagdollEntity():LookupAttachment( "eyes" ) ).Pos;
		trace.endpos = trace.start + Vector( 0, 0, 60 );
		trace.filter = LocalPlayer();
		
		local tr = util.TraceLine( trace );
		
		view.origin = tr.HitPos;
		view.angles = Angle( 90, DeathAngle, 0 );
		view.fov = 70;
		
		DeathAngle = DeathAngle + 7 * FrameTime();
		
		if( DeathAngle > 360 ) then
		
			DeathAngle = DeathAngle - 360;
		
		end
		
		return view;
	
	end

	if( ply:GetNWInt( "thirdperson" ) == 1 ) then

		local view = { }
		
		local mul = 1;
		
		if( ply:GetNWInt( "inversethirdperson" ) == 1 ) then
			
			mul = -1;
			view.angles = ply:GetAimVector():Angle() + Angle( 0, 180, 0 );
			
		else
		
			view.angles = ply:GetAimVector():Angle();
		
		end
		
		local tr = { }
		tr.start = ply:EyePos();
		tr.endpos = ply:EyePos() - ply:GetAimVector() * 100 * mul;
		tr.filter = ply;
		
		local trace = util.TraceLine( tr );
		
		view.origin = trace.HitPos + 10 * ply:GetAimVector() * mul;	
	  	
	  	return view;

	end
	
	-- Copy & Paste from Radecs APC to avoid conflicts
	--[[if ply:GetNetworkedInt("apc_view")==2 && !(ply:GetNetworkedBool("UsingCam") && ply:GetNetworkedEntity("apc1") && ply:GetNetworkedEntity("apc1"):IsValid()) then
	
		local e = ply:GetNetworkedEntity("apc1")
		if(e:IsValid()) then
			 if(e:GetNetworkedInt("apc_zoom")!=0) then APC_ZOOM = e:GetNetworkedInt("apc_zoom") end
			angles.pitch = LimitPitch(angles.pitch) - e:GetAngles().pitch
			local att = e:LookupAttachment("gun_def")
			local att = e:GetAttachment(att)
			local tracedata = {}
				tracedata.start = att.Pos
				tracedata.endpos = att.Pos - angles:Forward()*APC_ZOOM
				tracedata.mask = MASK_SOLID_BRUSHONLY
			local trace = util.TraceLine(tracedata)
			local view = {}
				view.origin 	= trace.HitPos
				view.angles		= angles
				view.fov 		= 70
			return view
		end
	end--]]
	
	if( not ClientVars["Conscious"] or ( not LocalPlayer():Alive() and not ply:GetRagdollEntity() ) ) then
	
	 	view.origin 	= UnconsciousViewPos or origin 
	 	view.fov =		UnconsciousFov;
	 	view.angles = UnconsciousViewAng or angles;
	 	
	 	if( CurTime() - UnconsciousTime >= 2 ) then
	 	
	 		if( not UnconsciousViewPos ) then
	 		
	 			UnconsciousViewPos = origin;
	 			UnconsciousViewAng = angles;
	 		
	 		end
	 	
	 	end
	 	
	 	UnconsciousFov = UnconsciousFov + UnconsciousFovVel * FrameTime();

	 	if( UnconsciousFov < 60 ) then
	 	
	 		UnconsciousFovVel = math.Clamp( UnconsciousFovVel + 40 * FrameTime(), -1000, 0 );
	 	
	 	end

	 	return view;
	 	
	end
	
	if( ClientVars["FreezeHead"] ) then
	
	 	view.origin 	= origin 
	 	view.fov 		= fov 
	 	
	 	if( FreezeHeadViewAngle ) then
	
	 		view.angles = FreezeHeadViewAngle;
	 		
	 		view = AddAlcoholMod( view );
	 		
	 		return view;
	 		
	 	end
	
	end
	
	
	if( TS.MapView ) then
	
		if( TS.MapViews[GetMap()] ) then
	
			view.origin = TS.MapViews[GetMap()].pos;
			view.angles = TS.MapViews[GetMap()].ang;
	
			return view;
	
		end
			
	end

	--Copy pasta--
	local wep = ply:GetActiveWeapon() 
	local view = {} 
 	view.origin 	= origin 
 	view.angles		= angles 
 	view.fov 		= fov 
	
	 if ( ValidEntity( wep ) ) then 
 	 
 		local func = wep.GetViewModelPosition 
 		if ( func ) then 
 			view.vm_origin,  view.vm_angles = func( wep, origin*1, angles*1 ) -- Note: *1 to copy the object so the child function can't edit it. 
 		end 
 		 
 		local func = wep.CalcView 
 		if ( func ) then 
 			view.origin, view.angles, view.fov = func( wep, ply, origin*1, angles*1, fov ) -- Note: *1 to copy the object so the child function can't edit it. 
 		end 
 	 
 	end 
	--End copy pasta--
	
	view = AddAlcoholMod( view );
		
	return view;

end

FreezeHeadViewAngle = nil;
FreezeHeadStartAngle = nil;
FreezeHeadStartYaw = 0;
FreezeHeadViewYaw = 0;
FreezeHeadStartPitch = 0;

function GM:CreateMove( cmd )

	if( ClientVars["FreezeHead"] ) then

		if( not FreezeHeadViewAngle or not FreezeHeadStartAngle ) then
		
			FreezeHeadViewAngle = cmd:GetViewAngles();
			FreezeHeadStartAngle = cmd:GetViewAngles();
			FreezeHeadStartYaw = FreezeHeadViewAngle.yaw;
			FreezeHeadStartPitch = FreezeHeadViewAngle.pitch;
			FreezeHeadViewYaw = FreezeHeadStartYaw;
		
		else
		
			local origyaw = FreezeHeadViewAngle.yaw;
			local origpitch = FreezeHeadViewAngle.pitch;
			
			FreezeHeadViewAngle.pitch = FreezeHeadViewAngle.pitch + ( cmd:GetViewAngles().pitch - FreezeHeadStartAngle.pitch );

			local cmdyaw = 0;
			
			if( origyaw < -170 ) then
				
				if( cmd:GetViewAngles().yaw > 0 and FreezeHeadStartAngle.yaw < 0 ) then
					cmdyaw = cmd:GetViewAngles().yaw - 360;
				else
					cmdyaw = cmd:GetViewAngles().yaw;
				end
			
			else
			
				cmdyaw = cmd:GetViewAngles().yaw;
			
			end
			
			local offset = ( cmdyaw - FreezeHeadStartAngle.yaw );
			
			FreezeHeadViewAngle.yaw = FreezeHeadViewAngle.yaw + offset;
			FreezeHeadViewAngle.roll = FreezeHeadViewAngle.roll + ( cmd:GetViewAngles().roll - FreezeHeadStartAngle.roll );
			
			if( FreezeHeadViewAngle.yaw > FreezeHeadStartYaw + 90 or FreezeHeadViewAngle.yaw < FreezeHeadStartYaw - 90 ) then
				FreezeHeadViewAngle.yaw = origyaw;
			end

			if( FreezeHeadViewAngle.pitch < FreezeHeadStartPitch - 70 ) then
				FreezeHeadViewAngle.pitch = origpitch;
			end

			if( FreezeHeadViewAngle.pitch > FreezeHeadStartPitch + 70 ) then
				FreezeHeadViewAngle.pitch = origpitch;
			end
	
			FreezeHeadStartAngle.pitch = FreezeHeadViewAngle.pitch;
	
			cmd:SetViewAngles( FreezeHeadStartAngle );
			
		end
		
	end

end

WalkToggle = false
IsCrouching = false

function GM:PlayerBindPress( ply, bind, down )

	--Chat window
	if( string.find( bind, "messagemode" ) ) then
	
		RunConsoleCommand( "eng_istyping", "" );
		OpenChatBox();
		return true;
	
	end
	
	if( bind == "+walk" and !ply:KeyDown( IN_SPEED ) ) then
	
		if( WalkToggle ) then
	
			RunConsoleCommand( "-back" );
			RunConsoleCommand( "-forward" );
			RunConsoleCommand( "-moveright" );
			RunConsoleCommand( "-moveleft" );
			
			WalkToggle = false;
		
		else
		
			if( ply:KeyDown( IN_FORWARD ) ) then
			
				WalkToggle = true;
				RunConsoleCommand( "+forward" );
			
			end
			
			if( ply:KeyDown( IN_BACK ) ) then
			
				WalkToggle = true;
				RunConsoleCommand( "+back" );
			
			end
			
			if( ply:KeyDown( IN_MOVELEFT ) ) then
			
				WalkToggle = true;
				RunConsoleCommand( "+moveleft" );
			
			end
			
			if( ply:KeyDown( IN_MOVERIGHT ) ) then
			
				WalkToggle = true;
				RunConsoleCommand( "+moveright" );
			
			end
		
		end
	
	end
	
	if( bind == "+jump" ) then
	
		if( ClientVars["Sprint"] < 15 or not ClientVars["CanSprint"] ) then
			return true;
		end
	
	end
	
	--Attack binds
	if( bind == "+attack" ) then
	
		if( ActionMenuOn ) then 
		
			return true;
		
		end
	
		if( WeaponsMenuVisible ) then
		
			if(  WeaponsTabs[SelectedTab] and WeaponsTabs[SelectedTab][SelectedSlot] ) then
				RunConsoleCommand( "rp_selectweapon", WeaponsTabs[SelectedTab][SelectedSlot].Class );
			end
			
			WeaponsMenuVisible = false;
			return true;
			
		end
	
	end
	
	--Weapon selection shit--
	if( string.sub( bind, 1, 4 ) == "slot" ) then
	
		local id = tonumber( string.sub( bind, 5 ) );
		
		if( id > 0 and id < 4 ) then
		
			WeaponsMenuFadeTime = CurTime() + 3;
			WeaponsMenuFadeAlpha = 255;
			
			if( SelectedTab == id and WeaponsMenuVisible ) then
			
				SelectedSlot = SelectedSlot + 1;
				
				if( SelectedSlot > GetMaxWeaponSlotIndex( SelectedTab ) ) then 
					SelectedSlot = 1;
				end
			
				if( GetWeaponSlotCount( SelectedTab ) > 0 ) then
			
					while( not WeaponsTabs[SelectedTab][SelectedSlot] ) do
				
						SelectedSlot = SelectedSlot + 1;
						
						if( SelectedSlot > GetMaxWeaponSlotIndex( SelectedTab ) ) then 
							SelectedSlot = 1;
						end
						
					end
					
				end
				
			else
			
				SelectedTab = id;
				SelectedSlot = 1;
				WeaponsMenuVisible = true;
				
				if( GetWeaponSlotCount( SelectedTab ) > 0 ) then
				
					while( not WeaponsTabs[SelectedTab][SelectedSlot] ) do
				
						SelectedSlot = SelectedSlot + 1;
						
					end
					
				end
				
			end
		
		end
	
	end
	
	if( not LocalPlayer():KeyDown( IN_ATTACK ) and bind == "invprev" ) then
	
		if( WeaponsMenuVisible ) then
		
			SelectedSlot = SelectedSlot - 1;
			
			if( SelectedSlot < 1 ) then
			
				SelectedTab = SelectedTab - 1;
				
				if( SelectedTab < 1 ) then
				
					SelectedTab = 3;
				
				end
				
				SelectedSlot = GetMaxWeaponSlotIndex( SelectedTab );
			
			end
			
			while( not WeaponsTabs[SelectedTab][SelectedSlot] ) do
				SelectedSlot = SelectedSlot - 1;
				
				if( SelectedSlot < 1 ) then
			
					SelectedTab = SelectedTab - 1;
					
					if( SelectedTab < 1 ) then
					
						SelectedTab = 3;
					
					end
					
					SelectedSlot = GetMaxWeaponSlotIndex( SelectedTab );
				
				end
			end
			
			WeaponsMenuFadeTime = CurTime() + 3;
			WeaponsMenuFadeAlpha = 255;
			

		
		else
		
			WeaponsMenuVisible = true;
			WeaponsMenuFadeTime = CurTime() + 3;
			WeaponsMenuFadeAlpha = 255;
			
		end
	
	end
	
	if( not LocalPlayer():KeyDown( IN_ATTACK ) and bind == "invnext" ) then
	
		if( WeaponsMenuVisible ) then
		
			SelectedSlot = SelectedSlot + 1;
			WeaponsMenuFadeAlpha = 255;
			
			WeaponsMenuFadeTime = CurTime() + 3;
			
			if( SelectedSlot > GetMaxWeaponSlotIndex( SelectedTab ) ) then
			
				SelectedTab = SelectedTab + 1;
				SelectedSlot = 1;
								
				if( SelectedTab > 3 ) then
				
					SelectedTab = 1;
				
				end
			
			end
			
			while( not WeaponsTabs[SelectedTab][SelectedSlot] ) do
			
				SelectedSlot = SelectedSlot + 1;
			
				if( SelectedSlot > GetMaxWeaponSlotIndex( SelectedTab ) ) then
				
					SelectedTab = SelectedTab + 1;
					SelectedSlot = 1;
									
					if( SelectedTab > 3 ) then
					
						SelectedTab = 1;
					
					end
				
				end
			
			end
		
		else
		
			WeaponsMenuVisible = true;
			WeaponsMenuFadeTime = CurTime() + 3;
			WeaponsMenuFadeAlpha = 255;
	
		end
	
	end
	--End weapon selection shit--

end

function CCToggleHolster( ply, cmd, arg )

	local weap = ply:GetActiveWeapon();
	
	if( weap:IsValid() ) then
	
		local class = weap:GetClass();
		
		if( class == "weapon_physcannon" or
			class == "weapon_physgun" or
			class == "gmod_tool" or
			class == "ts2_zipties" ) then return; end
	
		local holstered = !ClientVars["Holstered"];
		ClientVars["Holstered"] = holstered;
	
		if( not holstered ) then
	
			weap:GetTable().Primary.PositionMode = 2;
			weap:GetTable().Primary.PositionTime = .3;
			weap:GetTable().Primary.PositionMul = 1;
			
		else
		
			weap:GetTable().Primary.PositionMode = 3;
			weap:GetTable().Primary.PositionTime = .3;
			weap:GetTable().Primary.PositionMul = 0;
					
		end
	
		RunConsoleCommand( "eng_toggleholster", "" );
	
	end

end
concommand.Add( "rp_toggleholster", CCToggleHolster );

---------------------------------------
-- MISC CLIENT FUNCTIONS
---------------------------------------

function ApplyMaxCharacters( obj, len )

	obj.OnTextChanged = function() 
	
		if( string.len( obj:GetValue() ) == len ) then
			obj.MaxString = obj:GetValue();
		end
		
		if( string.len( obj:GetValue() ) > len ) then
			obj:SetText( obj.MaxString );
		end
		
	end

end

function ActionMenuCursorIsOn( x, y, w, h )

	local x2 = x + w;
	local y2 = y + h;
	
	local sx = ScrW() / 2;
	local sy = ScrH() / 2;
	
	if( sx >= x and sx <= x2 ) then
	
		if( sy >= y and sy <= y2 ) then
		
			return true;
		
		end
	
	end
	
	return false;

end



 
 --Unneeded Gear hooks.
hook.Remove( "PlayerBindPress", "GearPlayerBindPress" );
hook.Remove( "CalcView", "GearCalcView" );
hook.Remove( "Think", "GearThink" );
hook.Remove( "HUDShouldDraw", "GearHUDShouldDraw" );
 
PostClientsideLoad();

local function PlayerPopUpMsg( msg )

	local title = msg:ReadString();
	local text = msg:ReadString();	
	CreateOkPanel( title, text );
	
	gui.EnableScreenClicker( true );

end
usermessage.Hook( "PPM", PlayerPopUpMsg );

local function PlayerAdminWarn( msg )

	local adminmsg = msg:ReadString();
	local text = msg:ReadString();	
	CreateOkPanel( adminmsg, text );
	
	gui.EnableScreenClicker( true );

end
usermessage.Hook( "PAW", PlayerAdminWarn );



